package tech.wisefin.track.session;

import com.alibaba.fastjson.JSONArray;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.util.StringUtils;
import tech.wisefin.track.TrackConfiguration;

import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 前端的用户操作可以分为多个片段，以session作为唯一标识符
 */
@Data
@Entity
@Table(name = "session_tracks")
@EntityListeners({AuditingEntityListener.class})
public class SessionTrack implements Serializable {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    private String id;

    @Column(name = "session", unique = true, nullable = false)
    private String session;

    @Column(name = "video_file_name")
    private String videoFileName;

    @Column(name = "evidence")
    private String evidence;

    // 历史回溯信息
    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
    private List<SessionTrackFragment> fragments = new ArrayList<>();

    @CreatedDate
    @JsonProperty("created_at")
    @Column(name = "created_at", nullable = false)
    private Date createdAt;

    public SessionTrack() {

    }

    public SessionTrack(String session) {
        this.session = session;
    }

    public void addFragment(SessionTrackFragment fragment) {
        if (isLocked()) {
            throw new RuntimeException("视频已生成上链，不允许修改！");
        }
        if (fragment.getEvents() != null) {
            this.getFragments().add(fragment);
        }
    }

    public int getWidth() {
        if (this.fragments != null && this.fragments.size() > 0) {
            SessionTrackFragment fragment = this.fragments.get(this.fragments.size() - 1);
            return fragment.getWidth();
        }
        return 1024;
    }

    public int getHeight() {
        if (this.fragments != null && this.fragments.size() > 0) {
            SessionTrackFragment fragment = this.fragments.get(this.fragments.size() - 1);
            return fragment.getHeight();
        }
        return 768;
    }

    public ReplayForm createReplay(TrackConfiguration config) {
        ReplayForm form = new ReplayForm();
        JSONArray events = new JSONArray();
        this.fragments.forEach((fragment) -> {
            JSONArray checkpoint = fragment.getEvents();
            if (checkpoint != null) {
                events.addAll(checkpoint);
            }
        });

        String prefix = config.getVideoRemotePrefix();
        prefix = prefix.endsWith("/") ? prefix : prefix + "/";
        form.setVideoUrl(prefix + this.getVideoFileName());
        form.setHeight(this.getHeight());
        form.setWidth(this.getWidth());
        form.setEvents(events);
        return form;
    }

    public boolean isLocked() {
        return !StringUtils.isEmpty(this.videoFileName) && !StringUtils.isEmpty(this.evidence);
    }
}
